#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "common.h"

char *alg_name[] = {
	/*cipher*/
	/*aes128*/
	"AES_128_ECB",
	"AES_128_CBC",
	"AES_128_CTR",
	"AES_128_CFB",
	"AES_128_OFB",

	/*aes192*/
	"AES_192_ECB",
	"AES_192_CBC",
	"AES_192_CTR",
	"AES_192_CFB",
	"AES_192_OFB",

	/*aes256*/
	"AES_256_ECB",
	"AES_256_CBC",
	"AES_256_CTR",
	"AES_256_CFB",
	"AES_256_OFB",

	/*sm4*/
	"SM4_ECB",
	"SM4_CBC",
	"SM4_CTR",
	"SM4_CFB",
	"SM4_OFB",

	/*hash*/
	"HASH_MD5",
	"HASH_SHA1",
	"HASH_SHA224",
	"HASH_SHA256",
	"HASH_SHA384",
	"HASH_SHA512",
	"HASH_SHA3_224",
	"HASH_SHA3_256",
	"HASH_SHA3_384",
	"HASH_SHA3_512",
	"HASH_SM3",

	/*hmac*/
	"HMAC_MD5",
	"HMAC_SHA1",
	"HMAC_SHA224",
	"HMAC_SHA256",
	"HMAC_SHA384",
	"HMAC_SHA512",
	"HMAC_SHA3_224",
	"HMAC_SHA3_256",
	"HMAC_SHA3_384",
	"HMAC_SHA3_512",
	"HMAC_SM3",

	"RANDOM",
};

int alg_val[] = {
	/*cipher*/
	/*aes128*/
	ABCRYPTO_CIPHER_AES_128_ECB,
	ABCRYPTO_CIPHER_AES_128_CBC,
	ABCRYPTO_CIPHER_AES_128_CTR,
	ABCRYPTO_CIPHER_AES_128_CFB,
	ABCRYPTO_CIPHER_AES_128_OFB,

	/*aes192*/
	ABCRYPTO_CIPHER_AES_192_ECB,
	ABCRYPTO_CIPHER_AES_192_CBC,
	ABCRYPTO_CIPHER_AES_192_CTR,
	ABCRYPTO_CIPHER_AES_192_CFB,
	ABCRYPTO_CIPHER_AES_192_OFB,

	/*aes256*/
	ABCRYPTO_CIPHER_AES_256_ECB,
	ABCRYPTO_CIPHER_AES_256_CBC,
	ABCRYPTO_CIPHER_AES_256_CTR,
	ABCRYPTO_CIPHER_AES_256_CFB,
	ABCRYPTO_CIPHER_AES_256_OFB,

	/*sm4*/
	ABCRYPTO_CIPHER_SM4_ECB,
	ABCRYPTO_CIPHER_SM4_CBC,
	ABCRYPTO_CIPHER_SM4_CTR,
	ABCRYPTO_CIPHER_SM4_CFB,
	ABCRYPTO_CIPHER_SM4_OFB,

	/*hash*/
	ABCRYPTO_HASH_MD5,
	ABCRYPTO_HASH_SHA1,
	ABCRYPTO_HASH_SHA224,
	ABCRYPTO_HASH_SHA256,
	ABCRYPTO_HASH_SHA384,
	ABCRYPTO_HASH_SHA512,
	ABCRYPTO_HASH_SHA3_224,
	ABCRYPTO_HASH_SHA3_256,
	ABCRYPTO_HASH_SHA3_384,
	ABCRYPTO_HASH_SHA3_512,
	ABCRYPTO_HASH_SM3,

	/*hmac*/
	ABCRYPTO_HMAC_MD5,
	ABCRYPTO_HMAC_SHA1,
	ABCRYPTO_HMAC_SHA224,
	ABCRYPTO_HMAC_SHA256,
	ABCRYPTO_HMAC_SHA384,
	ABCRYPTO_HMAC_SHA512,
	ABCRYPTO_HMAC_SHA3_224,
	ABCRYPTO_HMAC_SHA3_256,
	ABCRYPTO_HMAC_SHA3_384,
	ABCRYPTO_HMAC_SHA3_512,
	ABCRYPTO_HMAC_SM3,

	ABCRYPTO_RANDOM,
};

uint16_t abcrypto_get_alg(uint8_t *name)
{
	uint16_t i;

	for (i = 0; i < ARRAY_SIZE(alg_name); i++) {
		if (strcmp(alg_name[i], name) == 0)
			return alg_val[i];
	}

	return ABCRYPTO_INVALID_ALG;
}

uint32_t get_rand(uint8_t *a, uint32_t byteLen)
{
	int result = 0;
	int fd = open("/dev/urandom", O_RDONLY);
	if (fd < 0) {
		fd = open("/dev/random", O_RDONLY);
		if (fd < 0) {
			fprintf(stderr, "get rand fail\n");
			return 0;
		}
	}

	result = read(fd, a, byteLen);
	if (result < 0) {
		fprintf(stderr, "get rand fail 2\n");
	}

	close(fd);
	return result;
}

const char *get_algo_name(int alg)
{
	int i;
	for (i = 0; i < ARRAY_SIZE(alg_val); i++) {
		if (alg_val[i] == alg) {
			return alg_name[i];
		}
	}

	return "UNKNOWN";
}

void print_buf(uint8_t *name, uint8_t *buf, uint32_t len)
{
	uint32_t i;

	fprintf(stderr, "%s[0x%x]:\n", name, len);
	if (len > 256)
		len = 256;
	for (i = 0; i < len; i += 16) {
		fprintf(stderr,
			"\"\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%"
			"02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\\x%02x\"\n",
			buf[i + 0], buf[i + 1], buf[i + 2], buf[i + 3],
			buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7],
			buf[i + 8], buf[i + 9], buf[i + 10], buf[i + 11],
			buf[i + 12], buf[i + 13], buf[i + 14], buf[i + 15]);
	}
}
